{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## MLP MNIST classifier with no regularization "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n",
      "Using TensorFlow backend.\n",
      "WARNING: Logging before flag parsing goes to stderr.\n",
      "W0907 07:54:42.215584 4571895232 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:66: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.\n",
      "\n",
      "W0907 07:54:42.231258 4571895232 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:541: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.\n",
      "\n",
      "W0907 07:54:42.233897 4571895232 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:4432: The name tf.random_uniform is deprecated. Please use tf.random.uniform instead.\n",
      "\n",
      "W0907 07:54:42.278742 4571895232 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/site-packages/keras/optimizers.py:793: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead.\n",
      "\n",
      "W0907 07:54:42.306833 4571895232 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:3576: The name tf.log is deprecated. Please use tf.math.log instead.\n",
      "\n",
      "W0907 07:54:42.404133 4571895232 deprecation.py:323] From /usr/local/lib/python3.6/site-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.where in 2.0, which has the same broadcast rule as np.where\n",
      "W0907 07:54:42.453546 4571895232 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:1033: The name tf.assign_add is deprecated. Please use tf.compat.v1.assign_add instead.\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential_1\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "dense_1 (Dense)              (None, 256)               200960    \n",
      "_________________________________________________________________\n",
      "activation_1 (Activation)    (None, 256)               0         \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 256)               65792     \n",
      "_________________________________________________________________\n",
      "activation_2 (Activation)    (None, 256)               0         \n",
      "_________________________________________________________________\n",
      "dense_3 (Dense)              (None, 10)                2570      \n",
      "_________________________________________________________________\n",
      "activation_3 (Activation)    (None, 10)                0         \n",
      "=================================================================\n",
      "Total params: 269,322\n",
      "Trainable params: 269,322\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "Epoch 1/20\n",
      "60000/60000 [==============================] - 1s 24us/step - loss: 1.1886 - acc: 0.7232\n",
      "Epoch 2/20\n",
      "60000/60000 [==============================] - 1s 23us/step - loss: 0.4769 - acc: 0.8768\n",
      "Epoch 3/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.3752 - acc: 0.8960\n",
      "Epoch 4/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.3316 - acc: 0.9069\n",
      "Epoch 5/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.3040 - acc: 0.9136\n",
      "Epoch 6/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.2835 - acc: 0.9194\n",
      "Epoch 7/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.2670 - acc: 0.9243\n",
      "Epoch 8/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.2529 - acc: 0.9279\n",
      "Epoch 9/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.2402 - acc: 0.9323\n",
      "Epoch 10/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.2291 - acc: 0.9351\n",
      "Epoch 11/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.2192 - acc: 0.9380\n",
      "Epoch 12/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.2102 - acc: 0.9407\n",
      "Epoch 13/20\n",
      "60000/60000 [==============================] - 1s 23us/step - loss: 0.2016 - acc: 0.9428\n",
      "Epoch 14/20\n",
      "60000/60000 [==============================] - 2s 25us/step - loss: 0.1942 - acc: 0.9448\n",
      "Epoch 15/20\n",
      "60000/60000 [==============================] - 1s 24us/step - loss: 0.1869 - acc: 0.9470\n",
      "Epoch 16/20\n",
      "60000/60000 [==============================] - 2s 26us/step - loss: 0.1803 - acc: 0.9488\n",
      "Epoch 17/20\n",
      "60000/60000 [==============================] - 2s 26us/step - loss: 0.1740 - acc: 0.9505\n",
      "Epoch 18/20\n",
      "60000/60000 [==============================] - 1s 25us/step - loss: 0.1686 - acc: 0.9518\n",
      "Epoch 19/20\n",
      "60000/60000 [==============================] - 1s 23us/step - loss: 0.1631 - acc: 0.9535\n",
      "Epoch 20/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.1582 - acc: 0.9546\n",
      "10000/10000 [==============================] - 0s 10us/step\n",
      "\n",
      "Test accuracy: 95.4%\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "MLP network for MNIST digits classification\n",
    "Test accuracy: 95.4%\n",
    "'''\n",
    "\n",
    "from __future__ import absolute_import\n",
    "from __future__ import division\n",
    "from __future__ import print_function\n",
    "\n",
    "# numpy package\n",
    "import numpy as np\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Activation\n",
    "from keras.datasets import mnist\n",
    "from keras.utils import to_categorical\n",
    "\n",
    "# load mnist dataset\n",
    "(x_train, y_train), (x_test, y_test) = mnist.load_data()\n",
    "\n",
    "# compute the number of labels\n",
    "num_labels = len(np.unique(y_train))\n",
    "\n",
    "# convert to one-hot vector\n",
    "y_train = to_categorical(y_train)\n",
    "y_test = to_categorical(y_test)\n",
    "\n",
    "# image dimensions (assumed square)\n",
    "image_size = x_train.shape[1]\n",
    "input_size = image_size * image_size\n",
    "# for mlp, the input dim is a vector, so we reshape\n",
    "x_train = np.reshape(x_train, [-1, input_size])\n",
    "# we train our network using float data\n",
    "x_train = x_train.astype('float32') / 255\n",
    "x_test = np.reshape(x_test, [-1, input_size])\n",
    "x_test = x_test.astype('float32') / 255\n",
    "\n",
    "# network parameters\n",
    "batch_size = 128\n",
    "hidden_units = 256\n",
    "\n",
    "# this is 3-layer MLP with ReLU. No regularizer\n",
    "model = Sequential()\n",
    "model.add(Dense(hidden_units, input_dim=input_size))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Dense(hidden_units))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Dense(num_labels))\n",
    "# this is the output for one-hot vector\n",
    "model.add(Activation('softmax'))\n",
    "model.summary()\n",
    "\n",
    "# loss function for one-hot vector\n",
    "# use of sgd optimizer\n",
    "# accuracy is good metric for classification tasks\n",
    "model.compile(loss='categorical_crossentropy',\n",
    "              optimizer='sgd',\n",
    "              metrics=['accuracy'])\n",
    "# train the network\n",
    "model.fit(x_train, y_train, epochs=20, batch_size=batch_size)\n",
    "\n",
    "# validate the model on test dataset to determine generalization\n",
    "score = model.evaluate(x_test, y_test, batch_size=batch_size)\n",
    "print(\"\\nTest accuracy: %.1f%%\" % (100.0 * score[1]))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
